package com.yuanthink.commons.base;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.SQLQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.yuanthink.commons.cache.EntityUtils;
import com.yuanthink.commons.cache.NullObject;
import com.yuanthink.commons.helper.ServiceManager;

/**
 * 
 * @author 06peng
 *
 * @param <E>
 * @param <PK>
 */
public abstract class BaseHibernateDao<E, PK extends Serializable> extends
		HibernateDaoSupport implements EntityDao<E, PK> {

	private Class<E> entityClass;
	protected Logger logger = LoggerFactory.getLogger(getClass()); // NOSONAR
	private static final int DEFAULT_MAX_RESULTS = 2000;
	
	@SuppressWarnings("unchecked")
	public BaseHibernateDao() {
		this.entityClass = (Class<E>) ((ParameterizedType) getClass()
	            .getGenericSuperclass()).getActualTypeArguments()[0];
	}
	
	public void initDao() {
		if (getHibernateTemplate().getMaxResults() == 0) {
			setMaxResults(DEFAULT_MAX_RESULTS);
		}
	}

	/**
	 * 设置getHibernateTemplate方式使用时默认的最大返回条数.
	 * 
	 * @param maxResults
	 */
	public void setMaxResults(int maxResults) {
		getHibernateTemplate().setMaxResults(maxResults);
	}

	/**
	 * 获取getHibernateTemplate方式使用时默认的最大返回条数.
	 * 
	 * @return maxResult
	 */
	public int getMaxResults() {
		return getHibernateTemplate().getMaxResults();
	}
	
	protected Class<E> getEntityClass() {
		return entityClass;
	}
	    
	@SuppressWarnings("unchecked")
	@Override
	public E getById(PK id) {
		if (ServiceManager.cacheFactory == null) {
			return (E) getSession().get(getEntityClass(), id);
		}
		E obj = (E) EntityUtils.getObjectByCache(getEntityClass(), id);
		if (obj == null) {
			obj = (E) getSession().get(getEntityClass(), id);
			if (obj != null) {
				EntityUtils.putCache(getEntityClass(), obj);
			} else {
				EntityUtils.putCache(getEntityClass(), new NullObject(id));
			}
		}
		if (obj instanceof NullObject) {
			return null;
		}
		return obj;
	}

	@Override
	public void deleteById(PK id) {
		E obj = getById(id);
        if (obj != null) {
            delete(obj);
        }
	}

	@Override
	public void delete(E obj) {
		getSession().delete(obj);
	}

	@Override
	public void save(E entity) {
		Object pkValue = EntityUtils.getEntityPkValue(entity);
        if(pkValue instanceof Integer && ((Integer)pkValue)>0){
            throw new IllegalArgumentException("错误使用save方法");
        }
		getSession().save(entity);
		EntityUtils.clearCache(getEntityClass(), entity);
	}

	@Override
	public void update(E entity) {
		EntityUtils.clearCache(getEntityClass(), entity);
		getSession().update(entity);
	}

	@Override
	public void saveOrUpdate(E entity) {
		EntityUtils.clearCache(getEntityClass(), entity);
		getSession().saveOrUpdate(entity);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<E> findAll() {
		Criteria criteria = getSession().createCriteria(getEntityClass());
		return criteria.list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<E> search(String sql) {
		return (List<E>) getHibernateTemplate().find(sql);
	}

	@Override
	public int executeSQL(String sql) {
		SQLQuery sQLQuery = getSession().createSQLQuery(sql);
		return sQLQuery.executeUpdate(); 
	}
	
	@SuppressWarnings("unchecked")
	public List<E> findAllUsePageLimit(int start, int limit) {
		Criteria criteria = getSession().createCriteria(getEntityClass());
		criteria.setFirstResult(start);
		criteria.setMaxResults(limit);
		return (List<E>) criteria.list();
	}

}
